package com.hzhr.iot.login.util.generator;

import com.hzhr.iot.core.annotation.ApiImplicitInternalParams;
import com.hzhr.iot.core.util.HzhrFileUtil;
import com.hzhr.iot.core.util.HzhrStringUtils;
import com.hzhr.iot.core.util.generator.CommonMapperGenerator;
import com.hzhr.iot.core.util.generator.ConvertorGenerator;
import com.hzhr.iot.core.util.generator.SdkGenerator;
import com.hzhr.iot.core.util.generator.ServiceAspectGenerator;
import com.hzhr.iot.login.constant.Login_ErrorsEnum;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.util.StringUtils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Generator {
    public static void main(String[] args) throws Exception{
        String projectName = "login-service";
        String serviceName = "login-service";
        String shortName = "login";

        Class[] ignoredModelClass = {};

        //current serial : 0
        CommonMapperGenerator.generatorModels_2 = new ArrayList<CommonMapperGenerator.GeneratorModel1>() {
            {
                
            }
        };

        File directory = new File("");
        String rootPath = directory.getCanonicalPath() + "\\" + projectName + "\\src\\main\\java\\" + Generator.class.getPackage().getName().replace(".util.generator", "").replace(".", "\\");
        String rootPackageName = Generator.class.getPackage().getName().replace(".util.generator", "");;

        CommonMapperGenerator.projectName = projectName;
        CommonMapperGenerator.rootPath = rootPath;
        CommonMapperGenerator.rootPackageName = rootPackageName;

        ConvertorGenerator.projectName = projectName;
        ConvertorGenerator.rootPath = rootPath;
        ConvertorGenerator.rootPackageName = rootPackageName;

        String sdkRootPath = directory.getCanonicalPath() + "\\" + projectName + "-sdk" + "\\src\\main\\java\\" + Generator.class.getPackage().getName().replace(".util.generator", "").replace(".", "\\") + "\\sdk";
        SdkGenerator.projectName = projectName;
        SdkGenerator.rootPath = rootPath;
        SdkGenerator.sdkRootPath = sdkRootPath;
        SdkGenerator.rootPackageName = rootPackageName;
        SdkGenerator.serviceName = serviceName;
        SdkGenerator.shortName = shortName;

        ServiceAspectGenerator.projectName = projectName;
        ServiceAspectGenerator.rootPath = rootPath;
        ServiceAspectGenerator.rootPackageName = rootPackageName;

        //region AnnoGenerator
        LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
        List<File> files = HzhrFileUtil.getFiles(rootPath + "\\service");
        for (File file:
                files) {
            String fileName = file.getName();
            if (!fileName.equals("BaseService.java") && fileName.endsWith("Service.java")) {
                StringBuilder contentSb = new StringBuilder();

                FileInputStream fis = new FileInputStream(file);


                String line = null;
                boolean annoFlag = false;
                String resourceName = fileName.substring(0, fileName.lastIndexOf("Service.java"));
                String functionName = "";

                Map<String, List<String>> shuomingMap = new HashMap<>();
                BufferedReader br = new BufferedReader(new InputStreamReader(fis));
                br.mark((int)file.length() + 1);
                while ((line = br.readLine()) != null) {
                    if (annoFlag) {
                        if (!line.contains("//endregion")) {
                            List<String> shuoming = shuomingMap.get(functionName);
                            if (shuoming == null) {
                                shuoming = new ArrayList<>();
                            }
                            shuoming.add(line.substring(line.indexOf("//") + 2).replace(" ", "&nbsp;"));
                            shuomingMap.put(functionName, shuoming);
                        } else {
                            annoFlag = false;
                        }
                    }

                    if (line.contains("//region 说明 : ")) {
                        functionName = line.substring(line.indexOf(" : ") + 3, line.length());
                        annoFlag = true;
                    }
                }

                functionName = "";
                br.reset();
                while ((line = br.readLine()) != null) {
                    if (annoFlag) {
                        if (line.contains("//endregion")) {
                            contentSb.append("    /**\n");
                            List<String> shuoming = shuomingMap.get(functionName);
                            if (shuoming != null && shuoming.size() > 0) {
                                int i = 0;
                                for (String item:
                                        shuoming) {
                                    if (i == 0) {
                                        contentSb.append("     * " + item + " <br/><br/>\n");
                                    } else {
                                        contentSb.append("     * " + item + " <br/>\n");
                                    }

                                    i++;
                                }
                            }


                            Class<?> serviceClass = null;
                            try {
                                serviceClass = Class.forName(rootPackageName + ".service." + resourceName + "Service");
                            } catch (Exception e) {

                            }
                            if (serviceClass != null) {
                                Method[] serviceMethods = serviceClass.getDeclaredMethods();
                                for (Method serviceMethod:
                                        serviceMethods) {
                                    if (serviceMethod.getName().equals(functionName)) {
                                        String[] parameterNames = u.getParameterNames(serviceMethod);
                                        List<String> parameterNameList = new ArrayList<>();
                                        for (String parameterName:
                                                parameterNames) {
                                            parameterNameList.add(parameterName);
                                        }

                                        if (parameterNameList.contains("header")) {
                                            contentSb.append("     * @param header <br/>\n");

                                            Class<?> controllerClass = null;
                                            try {
                                                controllerClass = Class.forName(rootPackageName + ".controller." + resourceName + "Controller");
                                            } catch (Exception e) {

                                            }
                                            if (controllerClass != null) {
                                                Method[] controllerMethods = controllerClass.getMethods();
                                                for (Method controllerMethod:
                                                        controllerMethods) {
                                                    if (controllerMethod.getName().equals(functionName)) {
                                                        ApiImplicitInternalParams apiImplicitInternalParams = controllerMethod.getAnnotation(ApiImplicitInternalParams.class);
                                                        if (apiImplicitInternalParams != null) {
                                                            ApiImplicitParam[] apiImplicitParamArr = apiImplicitInternalParams.value();
                                                            for (ApiImplicitParam apiImplicitParam:
                                                                    apiImplicitParamArr) {
                                                                if ("header".equals(apiImplicitParam.paramType())) {
                                                                    contentSb.append("     * " + apiImplicitParam.name() + " : <br/>");
                                                                    if (!StringUtils.isEmpty(apiImplicitParam.value())) {
                                                                        contentSb.append("&nbsp&nbsp&nbsp&nbsp 说明 : " + apiImplicitParam.value() + ";<br/>");
                                                                    }
                                                                    if (!StringUtils.isEmpty(apiImplicitParam.required())) {
                                                                        contentSb.append("&nbsp&nbsp&nbsp&nbsp 是否必填 : " + apiImplicitParam.required() + ";<br/>");
                                                                    }
                                                                    if (!StringUtils.isEmpty(apiImplicitParam.defaultValue())) {
                                                                        contentSb.append("&nbsp&nbsp&nbsp&nbsp 默认值 : " + apiImplicitParam.defaultValue() + ";<br/>");
                                                                    }
                                                                    if (!StringUtils.isEmpty(apiImplicitParam.dataType())) {
                                                                        contentSb.append("&nbsp&nbsp&nbsp&nbsp 数据类型 : " + apiImplicitParam.dataType() + ";<br/>");
                                                                    }
                                                                    contentSb.append("\n");
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }

                                        String str = contentSb.substring(0, contentSb.length() - 1);
                                        contentSb = new StringBuilder();
                                        contentSb.append(str + "<br/>\n");

                                        if (parameterNameList.contains("query")) {
                                            contentSb.append("     * @param query <br/>\n");

                                            Class<?> controllerClass = null;
                                            try {
                                                controllerClass = Class.forName(rootPackageName + ".controller." + resourceName + "Controller");
                                            } catch (Exception e) {

                                            }
                                            if (controllerClass != null) {
                                                Method[] controllerMethods = controllerClass.getMethods();
                                                for (Method controllerMethod:
                                                        controllerMethods) {
                                                    if (controllerMethod.getName().equals(functionName)) {
                                                        ApiImplicitInternalParams apiImplicitInternalParams = controllerMethod.getAnnotation(ApiImplicitInternalParams.class);
                                                        if (apiImplicitInternalParams != null) {
                                                            ApiImplicitParam[] apiImplicitParamArr = apiImplicitInternalParams.value();
                                                            int i = 0;
                                                            for (ApiImplicitParam apiImplicitParam:
                                                                    apiImplicitParamArr) {
                                                                if ("query".equals(apiImplicitParam.paramType())) {
                                                                    contentSb.append("     * " + apiImplicitParam.name() + " : <br/>");
                                                                    if (!StringUtils.isEmpty(apiImplicitParam.value())) {
                                                                        contentSb.append("&nbsp&nbsp&nbsp&nbsp 说明 : " + apiImplicitParam.value() + ";<br/>");
                                                                    }
                                                                    if (!StringUtils.isEmpty(apiImplicitParam.required())) {
                                                                        contentSb.append("&nbsp&nbsp&nbsp&nbsp 是否必填 : " + apiImplicitParam.required() + ";<br/>");
                                                                    }
                                                                    if (!StringUtils.isEmpty(apiImplicitParam.defaultValue())) {
                                                                        contentSb.append("&nbsp&nbsp&nbsp&nbsp 默认值 : " + apiImplicitParam.defaultValue() + ";<br/>");
                                                                    }
                                                                    if (!StringUtils.isEmpty(apiImplicitParam.dataType())) {
                                                                        contentSb.append("&nbsp&nbsp&nbsp&nbsp 数据类型 : " + apiImplicitParam.dataType() + ";<br/>");
                                                                    }
                                                                    contentSb.append("\n");
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }

                                        str = contentSb.substring(0, contentSb.length() - 1);
                                        contentSb = new StringBuilder();
                                        contentSb.append(str + "<br/>\n");

                                        Class<?> controllerClass = null;
                                        try {
                                            controllerClass = Class.forName(rootPackageName + ".controller." + resourceName + "Controller");
                                        } catch (Exception e) {

                                        }
                                        if (controllerClass != null) {
                                            Method[] controllerMethods = controllerClass.getMethods();
                                            for (Method controllerMethod:
                                                    controllerMethods) {
                                                if (controllerMethod.getName().equals(functionName)) {
                                                    ApiImplicitParams apiImplicitParams = controllerMethod.getAnnotation(ApiImplicitParams.class);
                                                    if (apiImplicitParams != null) {
                                                        ApiImplicitParam[] apiImplicitParamArr = apiImplicitParams.value();
                                                        for (ApiImplicitParam apiImplicitParam:
                                                                apiImplicitParamArr) {
                                                            if ("path".equals(apiImplicitParam.paramType())) {
                                                                contentSb.append("     * @param " + apiImplicitParam.name() + " " + apiImplicitParam.value() + " <br/><br/>\n");
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }

                                        if (parameterNameList.contains("body")) {
                                            contentSb.append("     * @param body <br/><br/>\n");
                                        }

                                        contentSb.append("     * @throws ServiceException <br/>\n");
                                        for (Login_ErrorsEnum errorsEnum:
                                                Login_ErrorsEnum.values()) {
                                            if (errorsEnum.toString().startsWith(resourceName.toUpperCase() + "SERVICE_" + HzhrStringUtils.splitHumpStr(functionName, "_").toUpperCase() + "_")) {
                                                contentSb.append("     * " + errorsEnum.toString() + " : <br/>");
                                                contentSb.append("&nbsp&nbsp&nbsp&nbsp异常类型 : " + errorsEnum.getServiceExceptionCategory().getDes() + "<br/>");
                                                if (!StringUtils.isEmpty(errorsEnum.getBusiness())) {
                                                    contentSb.append("&nbsp&nbsp&nbsp&nbsp异常业务 : " + errorsEnum.getBusiness() + "<br/>");
                                                }
                                                contentSb.append("&nbsp&nbsp&nbsp&nbsp异常描述 : " + errorsEnum.getMessage() + "<br/>\n");
                                            }
                                        }

                                        if (parameterNameList.contains("body")) {
                                            contentSb.append("     * @see " + serviceMethod.getParameterTypes()[parameterNameList.indexOf("body")].getSimpleName() + " body <br/>\n");
                                        }
                                        if (!"void".equals(serviceMethod.getReturnType().getSimpleName())) {
                                            contentSb.append("     * @see " + serviceMethod.getReturnType().getSimpleName() + " result <br/>\n");
                                        }                                    }
                                }
                            }



                            contentSb.append("     */ \n");


                            contentSb.append(line + "\n");
                            annoFlag = false;
                        } else {
                            continue;
                        }
                    } else {
                        contentSb.append(line + "\n");
                    }

                    if (line.contains("//region javadoc注释 : ")) {
                        functionName = line.substring(line.indexOf(" : ") + 3, line.length());
                        annoFlag = true;
                    }
                }

                br.close();

                HzhrFileUtil.writeContent(rootPath + "\\service\\" + fileName, contentSb.substring(0, contentSb.length() - 1));
            }
        }



        List<File> files1 = HzhrFileUtil.getFiles(rootPath + "\\controller");
        for (File file1:
                files1) {
            String fileName = file1.getName();
            if (!fileName.equals("BaseController.java") && fileName.endsWith("Controller.java")) {
                StringBuilder contentSb = new StringBuilder();

                FileInputStream fis = new FileInputStream(file1);
                BufferedReader br = new BufferedReader(new InputStreamReader(fis));

                String line = null;
                boolean annoFlag = false;
                String resourceName = fileName.substring(0, fileName.lastIndexOf("Controller.java"));

                File serviceFile = new File(rootPath + "\\service\\" + resourceName + "Service.java");

                String functionName = "";

                FileInputStream fis1 = new FileInputStream(serviceFile);
                BufferedReader br1 = new BufferedReader(new InputStreamReader(fis1));
                br1.mark((int) serviceFile.length());

                Map<String, List<String>> shuomingMap = new HashMap<>();
                while ((line = br1.readLine()) != null) {
                    if (annoFlag) {
                        if (!line.contains("//endregion")) {
                            List<String> shuoming = shuomingMap.get(functionName);
                            if (shuoming == null) {
                                shuoming = new ArrayList<>();
                            }
                            shuoming.add(line.substring(line.indexOf("//") + 2));
                            shuomingMap.put(functionName, shuoming);
                        } else {
                            annoFlag = false;
                        }
                    }

                    if (line.contains("//region 说明 : ")) {
                        functionName = line.substring(line.indexOf(" : ") + 3, line.length());
                        annoFlag = true;
                    }
                }
                br1.reset();

                Map<String, List<String>> canshuMap = new HashMap<>();
                while ((line = br1.readLine()) != null) {
                    if (annoFlag) {
                        if (!line.contains("//endregion")) {
                            List<String> canshu = canshuMap.get(functionName);
                            if (canshu == null) {
                                canshu = new ArrayList<>();
                            }
                            canshu.add(line);
                            canshuMap.put(functionName, canshu);
                        } else {
                            annoFlag = false;
                        }
                    }

                    if (line.contains("//region 参数 : ")) {
                        functionName = line.substring(line.indexOf(" : ") + 3, line.length());
                        annoFlag = true;
                    }
                }
                br1.reset();

                Map<String, List<String>> qingqiuMap = new HashMap<>();
                while ((line = br1.readLine()) != null) {
                    if (annoFlag) {
                        if (!line.contains("//endregion")) {
                            List<String> qingqiu = qingqiuMap.get(functionName);
                            if (qingqiu == null) {
                                qingqiu = new ArrayList<>();
                            }
                            qingqiu.add(line);
                            qingqiuMap.put(functionName, qingqiu);
                        } else {
                            annoFlag = false;
                        }
                    }

                    if (line.contains("//region 请求 : ")) {
                        functionName = line.substring(line.indexOf(" : ") + 3, line.length());
                        annoFlag = true;
                    }
                }
                br1.reset();

                functionName = "";
                String type = "";
                while ((line = br.readLine()) != null) {
                    if (annoFlag) {
                        if (line.contains("//endregion")) {
                            if (type.equals("响应码")) {
                                contentSb.append("    @ApiResponses({\n");
                                contentSb.append("            @ApiResponse(code = 200, message = \"成功\"),\n");

                                Map<Integer, List<Login_ErrorsEnum>> responseMap = new HashMap<>();
                                for (Login_ErrorsEnum errorsEnum :
                                        Login_ErrorsEnum.values()) {
                                    if (errorsEnum.toString().startsWith(resourceName.toUpperCase() + "SERVICE_" + HzhrStringUtils.splitHumpStr(functionName, "_").toUpperCase() + "_")) {
                                        Integer code = errorsEnum.getHttpStatus().value();
                                        if (responseMap.get(code) == null) {
                                            List<Login_ErrorsEnum> errorsEnums = new ArrayList<>();
                                            errorsEnums.add(errorsEnum);
                                            responseMap.put(code, errorsEnums);
                                        } else {
                                            List<Login_ErrorsEnum> errorsEnums = responseMap.get(code);
                                            errorsEnums.add(errorsEnum);
                                            responseMap.put(code, errorsEnums);
                                        }
                                    }
                                }
                                for (Map.Entry<Integer, List<Login_ErrorsEnum>> entry :
                                        responseMap.entrySet()) {
                                    Integer code = entry.getKey();
                                    List<Login_ErrorsEnum> errorsEnums = entry.getValue();

                                    contentSb.append("            @ApiResponse(code = " + code + ", message = \"");
                                    for (Login_ErrorsEnum errorsEnum :
                                            errorsEnums) {
                                        contentSb.append("----异常代码 : " + errorsEnum.getCode() + "  \\n");
                                        contentSb.append("----异常类型 : " + errorsEnum.getServiceExceptionCategory().getDes() + "  \\n");
                                        if (!StringUtils.isEmpty(errorsEnum.getBusiness())) {
                                            contentSb.append("----异常业务 : " + errorsEnum.getBusiness() + "  \\n");
                                        }
                                        contentSb.append("----异常说明 : " + errorsEnum.getMessage() + "  \\n");
                                        contentSb.append("\\n");
                                    }
                                    contentSb.append("\", response = ResponseExceptionDto.class),\n");
                                }

                                contentSb.append("    })\n");

                                contentSb.append(line + "\n");
                                annoFlag = false;
                            } else if (type.equals("说明")) {
                                List<String> shuoming = shuomingMap.get(functionName);
                                if (shuoming != null && shuoming.size() > 0) {
                                    contentSb.append("    @ApiOperation(");
                                    contentSb.append("value=\"" + shuoming.get(0) + "\", ");
                                    contentSb.append("notes=\"");
                                    for (String item :
                                            shuoming) {
                                        contentSb.append(item + "  \\n");
                                    }
                                    contentSb.append("\",produces = \"application/json\")\n");
                                }

                                contentSb.append(line + "\n");
                                annoFlag = false;
                            } else if (type.equals("参数")) {
                                List<String> canshu = canshuMap.get(functionName);
                                if (canshu != null && canshu.size() > 0) {
                                    for (String item :
                                            canshu) {
                                        contentSb.append(item + "\n");
                                    }
                                }

                                contentSb.append(line + "\n");
                                annoFlag = false;
                            } else if (type.equals("请求")) {
                                List<String> qingqiu = qingqiuMap.get(functionName);
                                if (qingqiu != null && qingqiu.size() > 0) {
                                    for (String item :
                                            qingqiu) {
                                        contentSb.append(item + "\n");
                                    }
                                }

                                contentSb.append(line + "\n");
                                annoFlag = false;
                            }
                        } else {
                            continue;
                        }
                    } else {
                        contentSb.append(line + "\n");
                    }

                    if (line.contains("//region swagger响应码 : ")) {
                        functionName = line.substring(line.indexOf(" : ") + 3, line.length());
                        annoFlag = true;
                        type = "响应码";
                    }
                    if (line.contains("//region swagger说明 : ")) {
                        functionName = line.substring(line.indexOf(" : ") + 3, line.length());
                        annoFlag = true;
                        type = "说明";
                    }
                    if (line.contains("//region swagger参数 : ")) {
                        functionName = line.substring(line.indexOf(" : ") + 3, line.length());
                        annoFlag = true;
                        type = "参数";
                    }
                    if (line.contains("//region 请求 : ")) {
                        functionName = line.substring(line.indexOf(" : ") + 3, line.length());
                        annoFlag = true;
                        type = "请求";
                    }

                }

                br.close();

                HzhrFileUtil.writeContent(rootPath + "\\controller\\" + fileName, contentSb.substring(0, contentSb.length() - 1));
            }
        }
        //endregion

        ServiceAspectGenerator.run();
        SdkGenerator.syncConstant();
        SdkGenerator.syncModel(ignoredModelClass);
        SdkGenerator.updateSdkModel();
        SdkGenerator.updateSdkConstant();
        SdkGenerator.generateService();
    }
}
